package com.loukou.lkt.lkt.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.loukou.lkt.lkt.bo.GoodsBo;
import com.loukou.lkt.lkt.bo.Query;
import com.loukou.lkt.lkt.bo.SupplierGoodsBo;
import com.loukou.lkt.lkt.dao.GoodsCostDao;
import com.loukou.lkt.lkt.dao.GoodsDao;
import com.loukou.lkt.lkt.dao.GoodsStockDao;
import com.loukou.lkt.lkt.dao.SupplierGoodsDao;
import com.loukou.lkt.lkt.entity.Goods;
import com.loukou.lkt.lkt.entity.GoodsCost;
import com.loukou.lkt.lkt.entity.GoodsStock;
import com.loukou.lkt.lkt.entity.OrderOperateLog;
import com.loukou.lkt.lkt.entity.SupplierGoods;
import com.loukou.lkt.lkt.enums.GoodsStockPositionTypeEnum;
import com.loukou.lkt.lkt.enums.GoodsStockStateEnum;
import com.loukou.lkt.lkt.enums.OrderOperateLogTypeEnum;
import com.loukou.lkt.lkt.resp.PageModel;
import com.loukou.lkt.lkt.resp.RespDto;
import com.loukou.lkt.lkt.resp.SupplierGoodsInfoDto;
import com.loukou.lkt.lkt.service.SupplierGoodsService;

@Service
public class SupplierGoodsServiceImpl implements SupplierGoodsService {

	@Autowired
	private SupplierGoodsDao supplierGoodsDao;
	@Autowired
	private GoodsDao goodsDao;
	@Autowired
	private GoodsCostDao goodsCostDao;

	@Autowired
	private GoodsStockDao goodsStockDao;

	@Override
	public PageModel<SupplierGoodsInfoDto> getSupplierGoodsInfoList(int warehouseId, int supplierId, int pageNum,
			int pageSize) {
		Sort sort = new Sort(Direction.DESC, "id");
		Pageable pageable = new PageRequest(pageNum - 1, pageSize, sort);
		Page<SupplierGoods> supplierGoodsPage = supplierGoodsDao.findBySupplierId(supplierId, pageable);
		List<SupplierGoodsInfoDto> supplierGoods = generateSupplierGoodsInfo(warehouseId, supplierGoodsPage);
		PageModel<SupplierGoodsInfoDto> result = new PageModel<SupplierGoodsInfoDto>();
		result.setDraw(2);
		result.setRecordsTotal(supplierGoodsPage.getTotalElements());
		result.setTotalPageNum(supplierGoodsPage.getTotalPages());
		result.setData(supplierGoods);
		return result;
	}

	private List<SupplierGoodsInfoDto> generateSupplierGoodsInfo(int warehouseId,
			Page<SupplierGoods> supplierGoodsPage) {
		List<SupplierGoods> supplierGoodsList = supplierGoodsPage.getContent();

		List<Integer> goodsIds = new ArrayList<Integer>();
		for (SupplierGoods supplierGoods : supplierGoodsList) {
			goodsIds.add(supplierGoods.getGoodsId());
		}

		Map<Integer, String> goodsIdNameMap = getGoodsNameMap(supplierGoodsList);

		Map<Integer, Integer> goodsStockMap = new HashMap<Integer, Integer>();
		List<GoodsStock> goodsStockList = goodsStockDao.findByWarehouseIdAndPositionTypeAndStockStateAndGoodsIdIn(
				warehouseId, GoodsStockPositionTypeEnum.TYPE_Normal.getId(), GoodsStockStateEnum.STATE_Normal.getId(),
				goodsIds);
		for (GoodsStock goodsStock : goodsStockList) {
			goodsStockMap.put(goodsStock.getGoodsId(), goodsStock.getStock());
		}

		List<SupplierGoodsInfoDto> dtos = new ArrayList<SupplierGoodsInfoDto>();
		for (SupplierGoods supplierGoods : supplierGoodsList) {
			SupplierGoodsInfoDto supplierGoodsInfoDto = new SupplierGoodsInfoDto();
			// supplierGoodsInfoDto.setTaosku(supplierGoods.getTaosku());
			// supplierGoodsInfoDto.setBn(supplierGoods.getBn());
			supplierGoodsInfoDto.setGoodsId(supplierGoods.getGoodsId());
			// supplierGoodsInfoDto.setGoodsSpecId(supplierGoods.getSpecId());
			if (goodsIdNameMap.containsKey(supplierGoods.getGoodsId())) {
				supplierGoodsInfoDto.setName(goodsIdNameMap.get(supplierGoods.getGoodsId()));
			} else {
				supplierGoodsInfoDto.setName("");
			}
			if (goodsStockMap.containsKey(supplierGoods.getGoodsId())) {
				supplierGoodsInfoDto.setAvailableNum(goodsStockMap.get(supplierGoods.getGoodsId()));
			} else {
				supplierGoodsInfoDto.setAvailableNum(0);
			}
			dtos.add(supplierGoodsInfoDto);
		}

		return dtos;
	}

	private List<SupplierGoods> getSupplierGoodsByGoodsName(String goodsName, int supplierId) {
		// 查goods－》goodsId－》supplierGoods－》根据supplierId过滤
		List<Goods> goods = goodsDao.findByGoodsNameLike(goodsName);
		List<SupplierGoods> supplierGoodsList = new ArrayList<SupplierGoods>();
		List<SupplierGoods> supplierGoods = supplierGoodsDao.findBySupplierId(supplierId);
		for (Goods g : goods) {
			for (SupplierGoods s : supplierGoods) {
				if (g.getGoodsId() == s.getGoodsId()) {
					supplierGoodsList.add(s);
				}
			}
		}
		return supplierGoodsList;
	}

	@Override
	public List<SupplierGoodsInfoDto> getSupplierGoodsByKeywords(int supplierId, String taosku, 
			String bn, String name, int warehouseId) {

		// Page<SupplierGoods> supplierGoodsPage = null;
		List<SupplierGoods> supplierGoodsList = supplierGoodsDao.findBySupplierId(supplierId);

		if (CollectionUtils.isEmpty(supplierGoodsList)) {
			return null;
		}

		List<Integer> goodsIds = new ArrayList<Integer>();
		for (SupplierGoods sg : supplierGoodsList) {
			goodsIds.add(sg.getGoodsId());
		}

		List<Goods> goods = goodsDao.findByGoodsIdIn(goodsIds);
		List<SupplierGoodsInfoDto> dtos = new ArrayList<SupplierGoodsInfoDto>();

		List<GoodsStock> goodsStockList = goodsStockDao.findByWarehouseIdAndPositionTypeAndStockStateAndGoodsIdIn(
				warehouseId, GoodsStockPositionTypeEnum.TYPE_Normal.getId(), 
				GoodsStockStateEnum.STATE_Normal.getId(), goodsIds);
		if (!StringUtils.isBlank(taosku)) {
			fillSupplierGoodsInfoDto(dtos, goods, taosku, bn, name, goodsStockList);
		
		}
		if (CollectionUtils.isEmpty(dtos) && !StringUtils.isBlank(bn)) {
			fillSupplierGoodsInfoDto(dtos, goods, taosku, bn, name, goodsStockList);
		}
		if (CollectionUtils.isEmpty(dtos)) {
			// 查goods－》goodsId－》supplierGoods－》根据supplierId过滤
			fillSupplierGoodsInfoDto(dtos, goods, taosku, bn, name, goodsStockList);
			supplierGoodsList = getSupplierGoodsByGoodsName(name, supplierId);
		}

		return null;
	}
	
	private void fillSupplierGoodsInfoDto(List<SupplierGoodsInfoDto> dtos, List<Goods> goods,
			String taosku, String bn, String name, List<GoodsStock> goodsStockList) {

		for(Goods g : goods) {
			if(StringUtils.equals(g.getSku(), taosku)) {
				SupplierGoodsInfoDto dto = new SupplierGoodsInfoDto();
				for(GoodsStock gs : goodsStockList) {
					if(gs.getGoodsId() == g.getGoodsId()) {
						dto.setAvailableNum(gs.getStock());
					}
				}
				
				dto.setBn(g.getBarcode());
				GoodsCost goodsCost = goodsCostDao.getGoodsCost(g.getGoodsId());
				if (goodsCost == null) {
					dto.setCostPrice(0);
				} else {
					dto.setCostPrice(goodsCost.getCostPrice());
				}
//				dto.setDeliveryNum(deliveryNum);
				dto.setName(g.getGoodsName());
				dtos.add(dto);
			}
		}
	}

	private Map<Integer, String> getGoodsNameMap(List<SupplierGoods> supplierGoodsList) {
		List<Integer> goodsIds = new ArrayList<Integer>();
		for (SupplierGoods supplierGoods : supplierGoodsList) {
			goodsIds.add(supplierGoods.getGoodsId());
		}

		Map<Integer, String> goodsIdNameMap = new HashMap<Integer, String>();
		List<Goods> goodsList = goodsDao.findByGoodsIdIn(goodsIds);
		for (Goods goods : goodsList) {
			goodsIdNameMap.put(goods.getGoodsId(), goods.getGoodsName());
		}
		return goodsIdNameMap;
	}

	@Override
	public RespDto<List<SupplierGoodsBo>> getList(int supplierId, final String taosku, final String bn,
			final String goodsName) {
		RespDto<List<SupplierGoodsBo>> resp = new RespDto<List<SupplierGoodsBo>>();
		List<SupplierGoodsBo> supplierGoodsBoList = new ArrayList<SupplierGoodsBo>();

		List<Goods> goodsList = goodsDao.findAll(new Specification<Goods>() {
			@Override
			public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				Query<Goods> q = new Query<Goods>(cb, root, query);
				q.like("sku", taosku);
				q.like("barcode", bn);
				q.like("goodsName", goodsName);
				return q.toPredicate();
			}
		});
		if (goodsList.size() == 0)
			return resp;
		Map<Integer, Goods> goodsMap = new HashMap<Integer, Goods>();
		Map<Integer, GoodsCost> goodsCostMap = new HashMap<Integer, GoodsCost>();

		List<Integer> getGoodsIds = new ArrayList<Integer>();

		for (Goods g : goodsList) {
			getGoodsIds.add(g.getGoodsId());
			goodsMap.put(g.getGoodsId(), g);
		}
		if (getGoodsIds.size() == 0)
			return resp;
		List<GoodsCost> getGoodsCostList = goodsCostDao.findByGoodsIdIn(getGoodsIds);
		for (GoodsCost gc : getGoodsCostList) {
			goodsCostMap.put(gc.getGoodsId(), gc);
		}

		List<SupplierGoods> supplierGoodsList = supplierGoodsDao.findBySupplierIdAndGoodsIdIn(supplierId, getGoodsIds);
		for (SupplierGoods sg : supplierGoodsList) {
			SupplierGoodsBo sgbo = new SupplierGoodsBo();
			if (goodsMap.get(sg.getGoodsId()) != null) {
				sgbo.setBarcode(goodsMap.get(sg.getGoodsId()).getBarcode());
				sgbo.setGoodsName(goodsMap.get(sg.getGoodsId()).getGoodsName());
				sgbo.setSalePrice(goodsMap.get(sg.getGoodsId()).getSalePrice());
				sgbo.setPacking(goodsMap.get(sg.getGoodsId()).getPacking());
				sgbo.setSku(goodsMap.get(sg.getGoodsId()).getSku());
				sgbo.setTax(goodsMap.get(sg.getGoodsId()).getTax());
			}
			sgbo.setGoodsId(sg.getGoodsId());
			sgbo.setId(sg.getId());
			sgbo.setRecentPurchasePrice(sg.getRecentPurchasePrice());
			sgbo.setSupplierId(sg.getSupplierId());

			supplierGoodsBoList.add(sgbo);
		}
		resp.setResult(supplierGoodsBoList);
		return resp;
	}

	@Override
	public RespDto<Integer> addGoods(List<GoodsBo> goodsBoList) {

		RespDto<Integer> res = new RespDto<Integer>();
		if (goodsBoList.size() == 0) {
			res.setCode(301);
			res.setMsg("请选择商品");
			return res;
		}
		List<SupplierGoods> supGoodsList = new ArrayList<SupplierGoods>();
		List<Integer> goodsIds = new ArrayList<Integer>();
		for (GoodsBo gsbo : goodsBoList) {
			goodsIds.add(gsbo.getGoodsId());
		}
		List<SupplierGoods> exSupGoodsList = supplierGoodsDao
				.findBySupplierIdAndGoodsIdIn(goodsBoList.get(0).getSupplierId(), goodsIds);
		goodsIds.clear();
		if (exSupGoodsList.size() > 0) {
			for (SupplierGoods s : exSupGoodsList) {
				goodsIds.add(s.getGoodsId());
			}
		}

		for (GoodsBo gsbo : goodsBoList) {
			if (goodsIds.indexOf(gsbo.getGoodsId()) < 0) {
				SupplierGoods sg = new SupplierGoods();
				sg.setGoodsId(gsbo.getGoodsId());
				sg.setSupplierId(gsbo.getSupplierId());
				supGoodsList.add(sg);
			}
		}
		supplierGoodsDao.save(supGoodsList);
		return res;
	}

	@Override
	public List<SupplierGoods> getSupplierGoods(int supplierId) {
		return supplierGoodsDao.findBySupplierId(supplierId);
	}

	@Override
	public RespDto<List<GoodsBo>> getGoodsPageList(final String taosku, final String bn, final String goodsName,
			final int pageIndex, final int pageNum) {
		RespDto<List<GoodsBo>> res = new RespDto<List<GoodsBo>>();
		List<GoodsBo> gsboList = new ArrayList<GoodsBo>();
		Page<Goods> goodsPageList = goodsDao.findAll(new Specification<Goods>() {
			@Override
			public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				Query<Goods> q = new Query<Goods>(cb, root, query);
				q.like("sku", taosku);
				q.like("barcode", bn);
				q.like("goodsName", goodsName);
				return q.toPredicate();
			}
		}, new PageRequest(pageIndex - 1, pageNum));
		if (goodsPageList.getSize() == 0)
			return res;
		// Map<Integer, Goods> goodsMap = new HashMap<Integer, Goods>();
		Map<Integer, GoodsCost> goodsCostMap = new HashMap<Integer, GoodsCost>();

		List<Integer> getGoodsIds = new ArrayList<Integer>();

		for (Goods g : goodsPageList.getContent()) {
			getGoodsIds.add(g.getGoodsId());

		}
		if (getGoodsIds.size() == 0)
			return res;
		List<GoodsCost> returnGoodsCostList = goodsCostDao.findByGoodsIdIn(getGoodsIds);

		for (GoodsCost gc : returnGoodsCostList) {
			goodsCostMap.put(gc.getGoodsId(), gc);
		}

		for (Goods g : goodsPageList.getContent()) {
			GoodsBo gsbo = new GoodsBo();
			BeanUtils.copyProperties(g, gsbo);
			if (goodsCostMap.get(g.getGoodsId()) != null)
				gsbo.setCostPrice(goodsCostMap.get(g.getGoodsId()).getCostPrice());
			gsboList.add(gsbo);
		}
		res.setResult(gsboList);
		return res;
	}

	@Override
	public RespDto<Integer> delete(List<SupplierGoodsBo> sbList) {
		RespDto<Integer> res = new RespDto<Integer>();
		List<Integer> ids = new ArrayList<Integer>();
		for (SupplierGoodsBo sb : sbList) {
			ids.add(sb.getId());
		}
		List<SupplierGoods> sgList = (List<SupplierGoods>) supplierGoodsDao.findAll(ids);
		supplierGoodsDao.delete(sgList);
		return res;
	}

	@Override
	public List<SupplierGoods> getGoodsBySupplierIds(List<Integer> ids) {
		return (List<SupplierGoods>) supplierGoodsDao.findAll(ids);
	}
	


}
